package com.sy.simpleegg.mvp.presenter

import androidx.lifecycle.LifecycleCoroutineScope
import com.google.gson.reflect.TypeToken
import com.sy.simpleegg.base.BasePresenter
import com.sy.simpleegg.bean.CheckMoneyBean
import com.sy.simpleegg.bean.RepCashDataBean
import com.sy.simpleegg.bean.SaveMoneyBean
import com.sy.simpleegg.bean.ScanBean
import com.sy.simpleegg.constant.ControlBoard
import com.sy.simpleegg.ext.getDeviceStatus
import com.sy.simpleegg.ext.logFile
import com.sy.simpleegg.http.HttpUtil
import com.sy.simpleegg.http.bean.VerifyQrCodeResp
import com.sy.simpleegg.http.callback.VerifyQrCodeCallback
import com.sy.simpleegg.mvp.contract.MainContract
import com.sy.simpleegg.mvp.model.MainModel
import com.sy.simpleegg.platform.BackstagePlatform
import com.sy.simpleegg.util.GsonUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.Call
import okhttp3.Response
import java.io.IOException
import java.util.Queue
import java.util.concurrent.LinkedBlockingDeque
import kotlin.math.max

class MainPresenter(private val lifecycleCoroutineScope: LifecycleCoroutineScope): BasePresenter<MainContract.Model, MainContract.View>(), MainContract.Presenter {

    private var handleJob: Job? = null
    private var isLoop = true
    private var postSaveCoinStatus = 0
    private var saveCoinPostResult = false

    private val orderQueue: Queue<ScanBean> = LinkedBlockingDeque<ScanBean>()
    private var isHandling = false

    private var outResult = -1//0-失败 1-成功 -1-出货中
    private var default_timeout = 31*1000
    private var verify_timeout = 15*1000

    override fun createModel(): MainContract.Model = MainModel()
    override fun init() {
        handleJob?.cancel()

        handleJob = lifecycleCoroutineScope.launch(Dispatchers.IO) {
            while (isLoop) {
                try {
                    run checkSize@{
                        if (orderQueue.size > 0) {
                            var scanBean: ScanBean? = null
                            while (!isHandling && orderQueue.poll().also { scanBean = it } != null) {
                                logFile("订单开始处理==========${scanBean!!.scanCode}")
                                isHandling = true
                                val isPaiBi = scanBean!!.isPaibi

                                if (isPaiBi){
                                    //派币出货
                                    var overCount = 0
                                    val interval = 100L
                                    val maxCount = default_timeout / interval
                                    outResult = -1
                                    mView?.out()
                                    do {
                                        delay(interval)
                                        overCount ++
                                    }while (overCount < maxCount && outResult == -1)

                                    isHandling = false
                                    delay(500)
                                    logFile("派币订单处理结束：完成==========${scanBean!!.scanCode} ${if (outResult == 1) "成功" else "失败"}")
                                    return@checkSize
                                }

                                //校验二维码
                                val localVerify = mModel?.verifyQrCode(scanBean!!.scanCode)?:false
                                if (!localVerify){
                                    isHandling = false
                                    delay(500)
                                    restartScan()
                                    logFile("订单处理结束：失败==========${scanBean!!.scanCode} 二维码不符合规则")
                                    return@checkSize
                                }

                                //通过http接口校验二维码合法性
                                var verifyResult = -1//0-校验不通过 1-校验通过 2-校验失败 -1-校验中
                                var verifyOverCount = 0
                                val verifyInterval = 100L
                                val verifyMaxCount = verify_timeout / verifyInterval

                                HttpUtil.verifyQrCode(scanBean!!.scanCode, object : VerifyQrCodeCallback() {
                                    override fun fail(call: Call?, e: IOException?) {
                                        logFile("接口校验二维码失败：${e?.message}")
                                        verifyResult = 2
                                    }

                                    override fun response(call: Call?, response: Response?) {
                                        val result = response?.let { resp ->
                                            val respStr = resp.body?.string()
                                            logFile("接口校验二维码结束:$respStr")
                                            val respBean = GsonUtil.getInstance()?.fromJson<VerifyQrCodeResp>(respStr, object : TypeToken<VerifyQrCodeResp>(){}.type)
                                            respBean?.Succeeded?:false
                                        }?:false
                                        verifyResult = if (result) 1 else 2
//                                        verifyResult = 1
                                    }
                                })

                                do {
                                    delay(verifyInterval)
                                    verifyOverCount ++

                                }while (verifyOverCount < verifyMaxCount && verifyResult == -1)

                                if (verifyResult == -1 || verifyResult == 2){
                                    isHandling = false
                                    delay(500)
                                    restartScan()
                                    logFile("订单处理结束：接口校验二维码异常==========${scanBean!!.scanCode}")
                                    return@checkSize
                                }

                                //开始出货
                                var overCount = 0
                                val interval = 100L
                                val maxCount = default_timeout / interval
                                outResult = -1
                                mView?.out()
                                do {
                                    delay(interval)
                                    overCount ++
                                }while (overCount < maxCount && outResult == -1)

                                isHandling = false
                                delay(10000)
                                restartScan()
                                logFile("订单处理结束：完成==========${scanBean!!.scanCode} ${if (outResult == 1) "成功" else "失败"}")
                                return@checkSize
                            }
                        }
                    }
                    delay(500)
                } catch (e: Exception) {
                    e.printStackTrace()
                    logFile("handleJob异常：${e.message}")
                    isHandling = false
                    restartScan()
                }
            }
        }
    }


    override fun loopSaveCoin() {

    }

    override fun initMqtt() {
        mModel?.initMqtt()
    }

    override fun initDeviceSerialport() {
        mModel?.initDeviceSerialport()
    }

    override fun outChannel(channelNumber: Int) {
        mModel?.outChannel(channelNumber)
    }

    override fun testChannel(channelNumber: Int) {
        mModel?.testChannel(channelNumber)
    }

    override fun clearCoins(k: String, coins: Long) {
        lifecycleCoroutineScope.launch {
            withContext(Dispatchers.IO){
                mModel?.clearCoins(k, coins)
            }
        }
    }

    override fun checkReceiveMoney(tempMoney: Long, checkMoney: Long) {
        lifecycleCoroutineScope.launch {
            var result: CheckMoneyBean
            withContext(Dispatchers.IO){
                result = mModel?.checkReceiveMoney(tempMoney, checkMoney)?: CheckMoneyBean().apply { msg = "校验纸钞异常" }
            }
            mView?.checkMoneyResult(result)
        }
    }

    override fun saveMoney(checkMoney: Long, totalMoney: Long) {
        lifecycleCoroutineScope.launch {
            var result: SaveMoneyBean? = null
            withContext(Dispatchers.IO){
                result = mModel?.saveMoney(checkMoney, totalMoney)?: null
            }
            mView?.saveMoneyResult(result)
        }
    }

    override fun clearMarkMoney() {
        mModel?.clearMarkMoney()
    }

    override fun initCashPackageData(platform: BackstagePlatform) {
        lifecycleCoroutineScope.launch {
            withContext(Dispatchers.IO){
                mModel?.initCashPackageData(platform)
            }
        }
    }

    override fun controlBoardConnectChange(controlBoard: ControlBoard, isConnect: Boolean) {
        lifecycleCoroutineScope.launch {
            withContext(Dispatchers.IO){
                mModel?.controlBoardConnectChange(controlBoard, isConnect)
            }
        }
    }

    override fun saveCashData(cash: Long, coins: Long) {
        lifecycleCoroutineScope.launch {
            var repCashDataBean: RepCashDataBean? = null
            withContext(Dispatchers.IO){
                repCashDataBean = mModel?.saveCashData(cash, coins)
            }
            repCashDataBean?.let {
                mView?.postCashData(it.repData)
            }
        }
    }

    override fun creatClearOrder(orderNumber: String) {
        lifecycleCoroutineScope.launch {
            withContext(Dispatchers.IO){
                mModel?.createClearOrder(orderNumber)
            }
        }
    }

    override fun SaveCoinPostResult(result: Boolean) {
        postSaveCoinStatus = 1
        saveCoinPostResult = result
    }

    override fun consumeCoinPostResult(result: Boolean) {

    }

    override fun saveWithdrawalCoinOrder(platform: BackstagePlatform, orderData: Any) {
        lifecycleCoroutineScope.launch {
            val result = withContext(Dispatchers.IO){
                mModel?.saveWithdrawalCoinOrder(platform, orderData)
            }
            mView?.saveWithdrawalCoinOrderResult(result)
        }
    }

    override fun saveWriteOffOrder(platform: BackstagePlatform, orderData: Any) {
        lifecycleCoroutineScope.launch {
            val result = withContext(Dispatchers.IO){
                mModel?.saveWriteOffOrder(platform, orderData)
            }
            result?.let {
                mView?.saveWriteOffOrderResult(it)
            }
        }
    }

    override fun insertHttpOrder(
        platform: BackstagePlatform,
        transId: String,
        orderId: String,
        orderNumber: String,
        goodId: String,
        coins: String,
        money: String,
    ) {
        lifecycleCoroutineScope.launch {
            withContext(Dispatchers.IO){
                mModel?.insertHttpOrder(platform, transId, orderId, orderNumber, goodId, coins, money)
            }
        }
    }

    override fun getOrderSupplement(startDate: String, endDate: String) {
        lifecycleCoroutineScope.launch {
            mView?.loadSupplementData(mModel?.getOrderSupplement(startDate, endDate)?: mutableListOf())
        }
    }

    override fun setRealAmount(id: Long, realAmount: String) {
        lifecycleCoroutineScope.launch {
            mModel?.setRealAmount(id, realAmount)
        }
    }

    override fun verifyOrder(platform: BackstagePlatform, orderData: Any) {
        lifecycleCoroutineScope.launch {
            mView?.verifyOrder(mModel?.verifyOrder(platform, orderData))
        }
    }

    override fun createOneCoinOrder(coins: Long) {
        lifecycleCoroutineScope.launch {
            mView?.createOneCoinOrder(mModel?.createOneCoinOrder(coins))
        }
    }

    override fun uploadLog(logType: Int, logNumber: String) {
        lifecycleCoroutineScope.launch {
            mModel?.uploadLog(logType, logNumber)
        }
    }

    override fun receiveScanOrder(scanData: String) {
        orderQueue.add(ScanBean(scanData))
    }

    override fun recOutResult(success: Boolean) {
        if (isHandling){
            outResult = if (success) 1 else 0
        }
    }

    override fun paibi() {
        orderQueue.add(ScanBean("", true))
    }

    override fun detechView() {
        super.detechView()
        isLoop = false
        handleJob?.cancel()
    }

    private fun restartScan(){
        mView?.restartScan()
    }
}